﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;


namespace TextGenerator
{
    /// <summary>
    /// Generates permutation data based on a pattern.
    /// </summary>
    public class Permutator
    {
        /// <summary>
        /// The <see cref="InvalidOperationException"/> that is thrown when the <see cref="Pattern"/> 
        /// has not been initialized.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Reviewed. Suppression is OK here.")] 
        private readonly InvalidOperationException exInvalidOperation = new InvalidOperationException("Pattern not initiated.");

//TODO: Consider replacing the _REGEXSAFE constants with Regex.Escape.
        #region Constants.
        /// <summary>
        /// The characters that signify the beginning of a token.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        public const string SYMBOL_DELIMITER_PREFIX = "[[";

        /// <summary>
        /// The <see cref="Regex"/> safe <see cref="SYMBOL_DELIMITER_PREFIX"/>.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        private const string SYMBOL_DELIMITER_PREFIX_REGEXSAFE = @"\[\[";

        /// <summary>
        /// The characters that signify the ending of a token.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        public const string SYMBOL_DELIMITER_SUFFIX = "]]";

        /// <summary>
        /// The <see cref="Regex"/> safe <see cref="SYMBOL_DELIMITER_SUFFIX"/>.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        private const string SYMBOL_DELIMITER_SUFFIX_REGEXSAFE = @"\]\]";

        /// <summary>
        /// The characters that separate token members inside a token.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.OrderingRules", "SA1202:ElementsMustBeOrderedByAccess",
            Justification = "Reviewed. Suppression is OK here.")] [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore",
                Justification = "Reviewed. Suppression is OK here.")] public const string TOKEN_DIVISOR = "|";

        /// <summary>
        /// The <see cref="Regex"/> safe <see cref="TOKEN_DIVISOR"/>.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        private const string TOKEN_DIVISOR_REGEXSAFE = @"\|";

        /// <summary>
        /// The characters indicating a token reference.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        public const string REFERENCE_IDENTIFIER_PREFIX = @"\";

        /// <summary>
        /// The <see cref="Regex"/> safe <see cref="REFERENCE_IDENTIFIER_PREFIX"/>.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        private const string REFERENCE_IDENTIFIER_PREFIX_REGEXSAFE = @"\\";

        /// <summary>
        /// The string representation of a quotation mark.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        public const string QUOTATION_MARK = "\"";

        /// <summary>
        /// The <see cref="Regex"/> safe <see cref="QUOTATION_MARK"/>.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        private const string QUOTATION_MARK_REGEXSAFE = "\\\"";

        /// <summary>
        /// The string representation of a backslash.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        public const string BACKSLASH = "\\";

        /// <summary>
        /// The <see cref="Regex"/> safe <see cref="BACKSLASH"/>.
        /// </summary>
        [SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Reviewed. Suppression is OK here.")]
        private const string BACKSLASH_REGEXSAFE = "\\\\";
        #endregion Constants.

        #region Regular Expressions.
        /// <summary>
        /// The regular expression for locating both tokens and references in a pattern.
        /// </summary>
        private static readonly Regex RegexFindSymbols = new Regex(
            String.Format(
                @"{2}(?:\w+|{1}(?:[^{0}\\\r\n]|{3}{{1,}}.)+{1}|(?:\w+{4}|{1}(?:[^{0}\\\r\n]|{3}{{1,}}.)+{1}{4})+(?:\w+|{1}(?:[^{0}\\\r\n]|{3}{{1,}}.)+{1})|{3}\d+(?:{4}\w+|{4}{1}(?:[^{0}\\\r\n]|{3}{{1,}}.)+{1})*){5}",
                QUOTATION_MARK,
                QUOTATION_MARK_REGEXSAFE, 
                SYMBOL_DELIMITER_PREFIX_REGEXSAFE,
                REFERENCE_IDENTIFIER_PREFIX_REGEXSAFE, 
                TOKEN_DIVISOR_REGEXSAFE,
                SYMBOL_DELIMITER_SUFFIX_REGEXSAFE),
            RegexOptions.Compiled);

        /// <summary>
        /// The regular expression for locating tokens in a pattern.
        /// </summary>
        private static readonly Regex RegexMatchVariables = new Regex(
            String.Format(
                @"(?<={2})(?:\w+|{1}(?:[^{0}\\\r\n]|\\{{1,}}.)+{1}|(?:\w+{3}|{1}(?:[^{0}\\\r\n]|\\{{1,}}.)+{1}{3})+(?:\w+|{1}(?:[^{0}\\\r\n]|\\{{1,}}.)+{1}))(?={4})",
                QUOTATION_MARK, 
                QUOTATION_MARK_REGEXSAFE, 
                SYMBOL_DELIMITER_PREFIX_REGEXSAFE, 
                TOKEN_DIVISOR_REGEXSAFE,
                SYMBOL_DELIMITER_SUFFIX_REGEXSAFE),
            RegexOptions.Compiled);

        /// <summary>
        /// The regular expression for retrieving token references.
        /// </summary>
        private static readonly Regex RegexMatchReferences = new Regex(
            String.Format(
                @"(?<={2}{3})(\d+)({4}\w+|{4}{1}(?:[^{0}\\\r\n]|\\{{1,}}.)+{1})*(?={5})", 
                QUOTATION_MARK,
                QUOTATION_MARK_REGEXSAFE, 
                SYMBOL_DELIMITER_PREFIX_REGEXSAFE,
                REFERENCE_IDENTIFIER_PREFIX_REGEXSAFE, 
                TOKEN_DIVISOR_REGEXSAFE,
                SYMBOL_DELIMITER_SUFFIX_REGEXSAFE),
            RegexOptions.Compiled);

        /// <summary>
        /// The regular expression for splitting up a variable to its members by the <see cref="TOKEN_DIVISOR_REGEXSAFE"/>.
        /// </summary>
        private static readonly Regex RegexSplitTokenMembersByDivisor = new Regex(
            String.Format(
                @"\w+|{1}(?:[^|{0}\\\r\n]|[^|{0}\\\r\n]\|+|\\+.)+{1}|(?:\w+\||{1}(?:[^|{0}\\\r\n]|[^|{0}\\\r\n]\|+|\\+.)+{1}\|)+(?:\w+|{1}(?:[^|{0}\\\r\n]|[^|{0}\\\r\n]\|+|\\+.)+{1})",
                QUOTATION_MARK, 
                QUOTATION_MARK_REGEXSAFE, 
                TOKEN_DIVISOR_REGEXSAFE),
            RegexOptions.Compiled);

        /// <summary>
        /// The regular expression for separating the identifier from the conditional members by the <see cref="TOKEN_DIVISOR_REGEXSAFE"/>.
        /// </summary>
        private static readonly Regex RegexSplitReferencesByIdentifier = new Regex(
            @"^\d+", 
            RegexOptions.Compiled);

        /// <summary>
        /// The regular expression for separating the conditional members from the identifier by the <see cref="TOKEN_DIVISOR_REGEXSAFE"/>.
        /// </summary>
        private static readonly Regex RegexSplitReferencesByMembers = new Regex(
            String.Format(
                @"(?<=\d+{2})(?:(?:[^{0}\\\r\n]|\\{{1,}}.)+|{1}(?:[^{0}\\\r\n]|\\{{1,}}.)+{1})+", 
                QUOTATION_MARK,
                QUOTATION_MARK_REGEXSAFE, 
                TOKEN_DIVISOR_REGEXSAFE),
            RegexOptions.Compiled);

        /// <summary>
        /// The regular expression for "cleaning" a member, e.g. removing any leading and trailing quotation mark.
        /// </summary>
        private static readonly Regex RegexCleanMember = new Regex(
            String.Format(
                @"(?:(?<={1})(?:[^|{0}\\\r\n]|[^|{0}\\\r\n]\|+|\\+.)+(?={1})|\w+)", 
                QUOTATION_MARK,
                QUOTATION_MARK_REGEXSAFE), 
            RegexOptions.Compiled);
        #endregion Regular Expressions.

        #region Progress Reporting Members.
        /// <summary>
        /// Keeps track of how many items have been processed since the generation began.
        /// </summary>
        /// <remarks>
        /// This is used for calculating and reporting the progress in percent.
        /// </remarks>
        private double numberOfProcessed;

        /// <summary>
        /// The number of total items to process.
        /// </summary>
        /// <remarks>
        /// This is used for calculating and reporting the progress in percent.
        /// The total number of items to process is twice the number of permutations; 
        /// the assembly and the generation iterates over all permutations.
        /// </remarks>
        /// <seealso cref="Assemble"/>
        /// <seealso cref="Generate"/>
        private double numberToProcess;
        #endregion Progress Reporting Members.

        #region Operational Private Fields.
        /// <summary>
        /// An array containing the index number of the referenced variable.
        /// </summary>
        private int[] referenceIdentities;

        /// <summary>
        /// An array of lists containing the conditional reference members.
        /// </summary>
        private List<string>[] referenceMembers;

        /// <summary>
        /// An array of <see cref="Regex"/> with the regular expressions for replacing each 
        /// unique variable symbol in the initialized pattern.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The regular expressions will be used when replacing the variable symbol with the 
        /// corresponding member, as determined by the <see cref="Assemble"/> method.
        /// </para>
        /// <para>
        /// Since there may be several thousands or millions of permutations, but a fixed, 
        /// and comparatively very low, number of symbols, the regular expressions will be 
        /// the same and reused iteratively. Create one unique <see cref="Regex"/> for each variable 
        /// symbol (not one for each permutation). 
        /// </para>para>
        /// <para>
        /// Furthermore, use the original "symbol", not the stored "token" (see the nomenclature 
        /// description for this project). The reason for this is that the members stored by 
        /// the <see cref="Initialize(String)"/> method have been "cleaned", e.g. escaped 
        /// characters replaced, symbol delimiters removed etc. 
        /// </para>
        /// </remarks>
        private Regex[] regexesReplacingVariables;

        /// <summary>
        /// An array of <see cref="Regex"/> with the regular expressions for replacing each 
        /// unique reference symbol in the initialized pattern.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The regular expressions will be used when replacing the reference symbol with the 
        /// corresponding variable, and/or conditional reference variable.
        /// </para>
        /// <para>
        /// Since there may be several thousands or millions of permutations, but a fixed, 
        /// and comparatively very low, number of symbols, the regular expressions will be 
        /// the same and reused iteratively. Create one unique <see cref="Regex"/> for each reference 
        /// symbol (not one for each permutation). 
        /// </para>para>
        /// <para>
        /// Furthermore, use the original "symbol", not the stored "token" (see the nomenclature 
        /// description for this project). The reason for this is that the members stored by 
        /// the <see cref="Initialize(String)"/> method have been "cleaned", e.g. escaped 
        /// characters replaced, symbol delimiters removed etc. 
        /// </para>
        /// </remarks>
        private Regex[] regexesReplacingReferences;
        #endregion Operational Private Fields.


        /// <summary>
        /// Initializes a new instance of the <see cref="Permutator"/> class.
        /// </summary>
        /// <param name="appendNewLine">Determines whether to append a <see cref="Environment.NewLine"/> to each generated permutation.</param>
        public Permutator(bool appendNewLine)
        {
            AppendNewLine = appendNewLine;
        }

        #region Operational Methods.
        /// <summary>
        /// Initializes the permutator by parsing the pattern for variables and members.
        /// </summary>
        /// <param name="pattern">The pattern to parse.</param>
        /// <exception cref="OverflowException">When the number of permutations exceed <see cref="Int32.MaxValue"/>.</exception>
        public void Initialize(string pattern)
        {
            Initialize(null, null, pattern);
        }

        /// <summary>
        /// Initializes the permutator by parsing the pattern for variables and references.
        /// </summary>
        /// <param name="worker">The <see cref="BackgroundWorker"/> that handles the threading.</param>
        /// <param name="workerEvents">The event arguments used by the <see cref="BackgroundWorker"/>.</param>
        /// <param name="pattern">The pattern to parse.</param>
        /// <exception cref="OverflowException">When the number of permutations exceed <see cref="Int32.MaxValue"/>.</exception>
        public void Initialize(BackgroundWorker worker, DoWorkEventArgs workerEvents, string pattern)
        {
            // Verify the input data.
            if (String.IsNullOrEmpty(pattern))
                throw new ArgumentNullException();

            // Start the timer.
            Timer timer = new Timer();
            timer.Start();

            // Initialize properties.
//TODO: These should be put last in the method, if everything succeeded.
//TODO: Make sure to use only pattern, not Pattern, from here on.
            Pattern = pattern;
            Worker = worker;
            WorkerArguments = workerEvents;
            NumberOfPermutations = 1;

            // Get the number of variables and references.
            // Then create arrays to store the data. 
            // The list arrays will store the members of each 
            // variable/reference token.
            // The array with reference identities will hold the index
            // of the referenced variable for the current reference.
            // Note that the arrays store the data in sequential order, 
            // i.e. the information is stored in the same order it was 
            // found. This is important when generating the final 
            // string in the Generate() method as the symbols will be 
            // replaced in the same order as they are found, thus using 
            // the contents of these arrays in sequential order.
            int numberOfVariables = CountVariables(Pattern);
            int numberOfReferences = CountReferences(Pattern);
            List<string>[] variables = new List<string>[numberOfVariables];
            List<string>[] references = new List<string>[numberOfReferences];
            int[] referenceIdentities = new int[numberOfReferences];

            // Create regular expressions for each variable and reference.
            Regex[] replaceVariables = new Regex[numberOfVariables];
            Regex[] replaceReferences = new Regex[numberOfReferences];
//TODO: RegexMatchVariables and RegexMatchReferences could be updated so it wouldn't be necessary to add the prefix/suffix.
//TODO: Use the symbol constants and Regex.Escape instead of the regexsafe constants.


            // Loop through each variable token.
            MatchCollection variableTokens = RegexMatchVariables.Matches(Pattern);
            for (int i = 0; i < numberOfVariables; i++)
            {
                // Create a list that will hold all members of the current 
                // variable token.
                List<string> members = new List<string>();

                // Split up the token by all of its members.
                MatchCollection mc = RegexSplitTokenMembersByDivisor.Matches(variableTokens[i].Value);

                // Add each member to the list.
                // While doing so, "clean" the member immediately. The regular 
                // expression has already ascertained that the member is not empty 
                // (thus preventing the adding of empty strings).
                foreach (Match m in mc)
                    members.Add(CleanMember(m.Value));

                // Add the member list to the variable list.
                variables[i] = members;

                // Generate the regular expression for replacing the current 
                // variable symbol.
                replaceVariables[i] = new Regex(String.Concat(SYMBOL_DELIMITER_PREFIX_REGEXSAFE, Regex.Escape(variableTokens[i].Value), SYMBOL_DELIMITER_SUFFIX_REGEXSAFE));

                // IMPORTANT:
                // This may cause a number of permutations exceeding Int32.MaxValue.
                // To make sure this does not happen, enable "Check for aritmhetic 
                // overflow/underflow" in the project's build settings. Doing that 
                // will cause this operation to throw an OverflowException. That 
                // exception can then be handled by the calling method.
                // If this is not done, the integer will simply turn over to a 
                // negative number.
                this._numberOfPermutations *= members.Count;
            }

            // Loop through each reference token.
            MatchCollection referenceTokens = RegexMatchReferences.Matches(pattern);
            for (int j = 0; j < numberOfReferences; j++)
            {
                // Create a list that will hold all members of the current 
                // reference token.
                List<string> members = new List<string>();

                // Get the identifier, e.g. the number that is the index 
                // of the referenced variable. Also get any conditional 
                // reference members.
                string referenceIdentifier = RegexSplitReferencesByIdentifier.Match(referenceTokens[j].Value).Value;
                string referenceMember = RegexSplitReferencesByMembers.Match(referenceTokens[j].Value).Value;

                // Get the index of the referenced variable.
                // There is no need to use a try-catch statement here, 
                // as the regular expression already have ascertained that 
                // the value is indeed a number.
                int identifier = Int32.Parse(referenceIdentifier);

                // Get the substring containing the token members 
                // and split it up by its members.
                MatchCollection mc = RegexSplitTokenMembersByDivisor.Matches(referenceMember);

                // Make sure there is no reference index that is greater than the 
                // number of variables.
                if (identifier > variables.Length - 1)
                    throw new ArgumentException("Invalid reference.");

                // Make sure that if the reference is a conditional reference, 
                // it has exactly the same number of members as the reference variable.
//TODO: Create a custom exception with more details. Don't forget to update the exception handling in MainForm.Threading.cs.
                if (mc.Count != 0 && mc.Count != variables[identifier].Count)
                    throw new ArgumentException("The specified pattern has an inconsistent conditional reference.");

                // Add each member to the list.
                // While doing so, "clean" the member immediately. The regular 
                // expression has already ascertained that the member is not empty 
                // (thus preventing the adding of empty strings).
                foreach (Match m in mc)
                    members.Add(CleanMember(m.Value));

                // Generate the regular expression for replacing the current 
                // reference symbol.
                replaceReferences[j] = new Regex(String.Concat(SYMBOL_DELIMITER_PREFIX_REGEXSAFE, REFERENCE_IDENTIFIER_PREFIX_REGEXSAFE, Regex.Escape(referenceTokens[j].Value), SYMBOL_DELIMITER_SUFFIX_REGEXSAFE));

                // Store the variable index this reference is referring to.
                referenceIdentities[j] = identifier;

                // Store the conditional reference members.
                references[j] = members;
            }


            // Set the statistics for percentage calculation.
            // Note:
            // Do this when initializing in order to save 
            // processing time by not having to recalculate 
            // it every iteration when processing.
            this.numberOfProcessed = 0;
            this.numberToProcess = (double) this._numberOfPermutations * 2;

            // Initialized variables.
            this._numberOfVariables = numberOfVariables;
            this._numberOfReferences = numberOfReferences;
            this._variables = variables;
            this.referenceIdentities = referenceIdentities;
            this.referenceMembers = references;
            this.regexesReplacingVariables = replaceVariables;
            this.regexesReplacingReferences = replaceReferences;
            this._isInitialized = true;
            this._isGenerated = false;

            // Stop the timer.
            timer.Stop();
            Debug.WriteLine(String.Format("Initialized in: {0} seconds", timer.Duration));
        }

        /// <summary>
        /// Generates data based on the input pattern.
        /// </summary>
        public void Generate()
        {
            if (!IsInitialized)
                throw this.exInvalidOperation;


            // Create a list that will hold the final results 
            // of all generated permutations.
            List<string> generated = new List<string>(NumberOfPermutations);

            // Get the array with all combinations of variable indices.
            int[,] assembled = Assemble();

            // Start timing how long the assembly takes.
            Timer timer = new Timer();
            timer.Start();


            // Iterate through each permutation and create the text string.
            for (int r = 0; r < assembled.GetLength(0); r++)
            {
                // Abort the operation if the user has canceled.
                // Observe that a call to CancelAsync may have set 
                // CancellationPending to true just after the
                // last invocation of this method exits, so this 
                // code will not have the opportunity to set the 
                // DoWorkEventArgs.Cancel flag to true. This means
                // that RunWorkerCompletedEventArgs.Cancelled will
                // not be set to true in your RunWorkerCompleted
                // event handler. This is a race condition.
                if (Worker != null && Worker.CancellationPending)
                {
                    WorkerArguments.Cancel = true;
                    break;
                }

                // Get the pattern.
                // The initial pattern will be used as the basis 
                // for the replacement of the symbols with the 
                // regular expressions for each symbol.
                string gen = Pattern;

                // Replace all variable symbols.
                for (int c = 0; c < NumberOfVariables; c++)
                    gen = regexesReplacingVariables[c].Replace(gen, Variables[c][assembled[r, c]]);

                // Replace all reference symbols.
                for (int c = 0; c < NumberOfReferences; c++)
                {
                    // Replace the current reference.
                    // If it has no reference members, then use the variable 
                    // text; otherwise use the conditional reference member.
                    if (this.referenceMembers[c].Count == 0)
                        gen = regexesReplacingReferences[c].Replace(gen, Variables[this.referenceIdentities[c]][assembled[r, this.referenceIdentities[c]]]);
                    else
                        gen = regexesReplacingReferences[c].Replace(gen, this.referenceMembers[c][assembled[r, this.referenceIdentities[c]]]);
                }

                // Add the result to the list.
                generated.Add(AppendNewLine ? String.Concat(gen, Environment.NewLine) : gen);

                // Report the current progress.
                if (Worker != null)
                {
                    this.numberOfProcessed++;
                    Worker.ReportProgress(PercentageGenerated);
                }
            }

            // Stop the timer and report the duration.
            timer.Stop();
            Debug.WriteLine(String.Format("Generated in: {0} seconds", timer.Duration));

            this._permutations = generated;
            this._isGenerated = true;
        }

        /// <summary>
        /// Assembles an array of variable member indices based on the <see cref="Pattern"/>.
        /// </summary>
        /// <remarks>
        /// This is where the actual combination of the variable members take place. 
        /// Note that the references are not involved when assembling the combinations, as 
        /// the references are not contributory to the combinatorics.
        /// See <see cref="Initialize(string)"/> for the preparation of the literal members, 
        /// and <see cref="Generate"/> for the string operations replacing references and 
        /// compiling the result.
        /// </remarks>
        /// <returns>
        /// A two-dimensional array of indices referring to the member's indices in the 
        /// corresponding variable.
        /// The first dimension is the permutation.
        /// The second dimension is the variables.
        /// </returns>
        /// <exception cref="OutOfMemoryException">When the memory is exhausted by too many permutations.</exception>
        private int[,] Assemble()
        {
            if (!IsInitialized)
                throw this.exInvalidOperation;

            Timer timer = new Timer();
            timer.Start();

            // Create an array that will contain the indices of each variable 
            // member for each permutation.
            //
            // Note:
            // This may cause an OutOfMemoryException if the NumberOfPermutations 
            // is too great. This must be handled by the caller.
//TODO: This should be a private property/field.
            int[,] indices = new int[NumberOfPermutations, NumberOfVariables];
            
            // Loop through each permutation row.
            for (int r = 1; r < NumberOfPermutations; r++)
            {
                // Abort the operation if the user has canceled.
                // Note that a call to CancelAsync may have set 
                // CancellationPending to true just after the
                // last invocation of this method exits, so this 
                // code will not have the opportunity to set the 
                // DoWorkEventArgs.Cancel flag to true. This means
                // that RunWorkerCompletedEventArgs.Cancelled will
                // not be set to true in your RunWorkerCompleted
                // event handler. This is a race condition.
                if (Worker != null && Worker.CancellationPending)
                {
                    WorkerArguments.Cancel = true;
                    break;
                }

                // If there is only one variable, 
                // the permutation number will match the member 
                // index. Add it to the indices table.
                if (NumberOfVariables == 1)
                    indices[r, 0] = r;

                // Set indices, beginning with the last variable.
                // Loop through all variables in order to update 
                // the parent variables cascadingly.
                // 
                // Note:
                // If there is only one variable, this code block 
                // will not be executed. Hence, the if-else block 
                // above can be avoided.
                for (int c = NumberOfVariables - 1; c > 0; c--)
                {
                    // Check if the number of members was reached in the previous permutation.
                    if (indices[r - 1, c] >= Variables[c].Count - 1)
                    {
                        // All members of the current variable have been 
                        // added to previous permutations.

                        // Increase the parent variable by one.
                        // Note:
                        // If this makes the parent variable reach an index 
                        // higher than that variable's number of members, 
                        // this will automatically be amended in the next 
                        // loop. Thus, do not break in this case.
                        indices[r, c - 1] = indices[r - 1, c - 1] + 1;

                        // Reset the current variable to zero.
                        indices[r, c] = 0;
                    }
                    else
                    {
                        // The previous permutation did not contain the last member 
                        // of the current variable.

                        // Increase the current variable.
                        indices[r, c] = indices[r - 1, c] + 1;

                        // Use the same indices for the parent variables 
                        // as in the previous permutation.
                        for (int p = c - 1; p >= 0; p--)
                            indices[r, p] = indices[r - 1, p];

                        // Break the variable-loop, since the lowest variable 
                        // has not yet filled all members.
                        break;
                    }
                }

                // Report the current progress.
                if (Worker != null)
                {
                    this.numberOfProcessed++;
                    Worker.ReportProgress(PercentageGenerated);
                }
            }

            timer.Stop();
            Debug.WriteLine(String.Format("Assembled in: {0} seconds", timer.Duration));

            return indices;
        }

        /// <summary>
        /// Releases all memory consuming resources, 
        /// but retains all initialized settings.
        /// </summary>
        public void Purge()
        {
            this._isGenerated = false;
            this._permutations = new List<string>();
            this.numberOfProcessed = 0d;
        }

        /// <summary>
        /// Returns the <see cref="Permutator"/> to its initial state, 
        /// thus discarding any generated data and settings.
        /// </summary>
        public void Reset()
        {
            Purge();

            this._addNewLine = false;
            this._isInitialized = false;
            this._numberOfVariables = 0;
            this._numberOfReferences = 0;
            this._numberOfPermutations = 0;
            this._pattern = String.Empty;
            this._variables = null;
            this.referenceIdentities = null;
            this.referenceMembers = null;
            this._worker = null;
            this._workerArguments = null;
            this.numberToProcess = 0d;
            this.numberOfProcessed = 0d;
            this.regexesReplacingVariables = null;
            this.regexesReplacingReferences = null;
        }
        #endregion Operational Methods.

        #region Private Properties.
        private BackgroundWorker _worker;
        /// <summary>
        /// Gets or sets the <see cref="BackgroundWorker"/> handling the threading when generating.
        /// </summary>
        private BackgroundWorker Worker
        {
            get { return this._worker; }
            set { this._worker = value; }
        }

        private DoWorkEventArgs _workerArguments;
        /// <summary>
        /// Gets or sets the <see cref="DoWorkEventArgs"/> associated with the <see cref="Worker"/>.
        /// </summary>
        private DoWorkEventArgs WorkerArguments
        {
            get { return this._workerArguments; }
            set { this._workerArguments = value; }
        }

        /// <summary>
        /// Gets the number of percent currently processed.
        /// </summary>
        private int PercentageGenerated
        {
            get
            {
                if (this.numberOfProcessed == 0 || this.numberToProcess == 0d)
                    return 0;

                return (int) Math.Round(100 * this.numberOfProcessed / this.numberToProcess);
            }
        }
        #endregion Private Properties.

        #region Properties.
        private bool _isInitialized = false;
        /// <summary>
        /// Gets a value indicating whether the <see cref="Permutator"/> has been initialized.
        /// </summary>
        /// <seealso cref="Initialize"/>
        public bool IsInitialized
        {
            get { return this._isInitialized; }
        }

        private bool _isGenerated = false;
        /// <summary>
        /// Gets a value indicating whether any permutations has been generated based on the specified <see cref="Pattern"/>.
        /// </summary>
        /// <seealso cref="Generate"/>
        public bool IsGenerated
        {
            get { return this._isGenerated; }
        }

        private bool _addNewLine = false;
        /// <summary>
        /// Gets or sets a value indicating whether to append a <see cref="Environment.NewLine"/> to 
        /// each generated permutation.
        /// </summary>
        public bool AppendNewLine
        {
            get { return this._addNewLine; }
            set { this._addNewLine = value; }
        }

        private string _pattern = String.Empty;

        /// <summary>
        /// Gets the pattern.
        /// </summary>
        public string Pattern
        {
            get { return this._pattern; }
            private set
            {
                if (String.IsNullOrEmpty(value))
                    throw new ArgumentNullException();

                if (String.IsNullOrEmpty(value.Trim()))
                    throw new ArgumentNullException();

                this._pattern = value;
            }
        }

//TODO: This should be removed!
        private List<string>[] _variables;
        /// <summary>
        /// Gets an array with lists of each variable's members.
        /// </summary>
        public List<string>[] Variables
        {
            get
            {
                if (this._variables == null || !IsInitialized)
                    throw this.exInvalidOperation;

                return this._variables;
            }
        }

////TODO: This should be removed!
//        private List<string>[] _references;
//        /// <summary>
//        /// Gets an array with lists of each reference's members.
//        /// </summary>
//        public List<string>[] References
//        {
//            get
//            {
//                if (this._references == null || !IsInitialized)
//                    throw this.exInvalidOperation;

//                return this._references;
//            }
//        }

        private List<string> _permutations;
        /// <summary>
        /// Gets all generated permutations.
        /// </summary>
        /// <seealso cref="Generate"/>
        public List<string> Permutations
        {
            get
            {
                if (!IsInitialized)
                    throw this.exInvalidOperation;

                if (this._permutations == null || !IsGenerated)
                    throw new InvalidOperationException("Permutations not generated.");

                return this._permutations;
            }
        }

        private int _numberOfVariables;
        /// <summary>
        /// Gets the number of variables in the specified pattern.
        /// </summary>
        public int NumberOfVariables
        {
            get
            {
                if (!IsInitialized)
                    throw this.exInvalidOperation;

                return this._numberOfVariables;
            }
        }

        private int _numberOfReferences;
        /// <summary>
        /// Gets the number of references in the specified pattern.
        /// </summary>
        public int NumberOfReferences
        {
            get
            {
                if (!IsInitialized)
                    throw this.exInvalidOperation;

                return this._numberOfReferences;
            }
        }

        private int _numberOfPermutations = 0;
        /// <summary>
        /// Gets the total number of permutations in the specified pattern.
        /// </summary>
        public int NumberOfPermutations
        {
            get
            {
                if (!IsInitialized)
                    throw this.exInvalidOperation;

                return this._numberOfPermutations;
            }

            private set
            {
                if (value < 0)
                    throw new ArgumentOutOfRangeException("value", value, @"The number of permutations must be a positive integer.");

                this._numberOfPermutations = value;
            }
        }
        #endregion Properties.

        #region Static Methods.
        /// <summary>
        /// Counts the number of variables as defined by the specified pattern.
        /// </summary>
        /// <param name="pattern">The pattern containing the variables.</param>
        /// <returns>
        /// The number of variables in the specified pattern.
        /// </returns>
        public static int CountVariables(string pattern)
        {
            if (String.IsNullOrEmpty(pattern))
                return 0;

            if (String.IsNullOrEmpty(pattern.Trim()))
                return 0;

            return RegexMatchVariables.Matches(pattern).Count;
        }

        /// <summary>
        /// Counts the number of references as defined by the specified pattern.
        /// </summary>
        /// <param name="pattern">The pattern containing the references.</param>
        /// <returns>
        /// The number of references in the specified pattern.
        /// </returns>
        public static int CountReferences(string pattern)
        {
            if (String.IsNullOrEmpty(pattern))
                return 0;

            if (String.IsNullOrEmpty(pattern.Trim()))
                return 0;

            return RegexMatchReferences.Matches(pattern).Count;
        }


        /// <summary>
        /// Counts the number of combinations as defined by the specified pattern.
        /// </summary>
        /// <param name="pattern">The pattern containing the variables.</param>
        /// <returns>
        /// The total number of combinations in the specified pattern.
        /// </returns>
        /// <exception cref="OverflowException">If the number of permutations is greater than <see cref="Int32.MaxValue"/>.</exception>
        public static int CountPermutations(string pattern)
        {
            if (String.IsNullOrEmpty(pattern))
                return 0;

            if (String.IsNullOrEmpty(pattern.Trim()))
                return 0;

            // Set the initial count to 1.
            int count = 1;

            // Check each match.
            MatchCollection mc = RegexMatchVariables.Matches(pattern);
            foreach (Match m in mc)
            {
                // Split by the divisor.
                int c = RegexSplitTokenMembersByDivisor.Matches(m.Value).Count;

                // If the match is empty, disregard it.
                // Otherwise multiply with the number of members.
                //
                // IMPORTANT:
                // This may cause a number of permutations exceeding Int32.Max.
                // To make sure this does not happen, enable "Check for aritmhetic 
                // overflow/underflow" in the project's build settings. Doing that 
                // will cause this operation to throw an OverflowException. That 
                // exception can then be handled by the calling method.
                // If this is not done, the integer will simply turn over to a 
                // negative number.)
                if (m.Length > 0)
                    count *= c;
                else
                    count--;
            }

            return count;
        }

        /// <summary>
        /// Validates that the specified string is a valid variable symbol.
        /// </summary>
        /// <param name="symbol">The string to validate as a variable symbol.</param>
        /// <returns>
        /// True if the specified string is a valid variable symbol, 
        /// False otherwise.
        /// </returns>
        /// <remarks>
        /// A valid variable symbol begins with <see cref="SYMBOL_DELIMITER_PREFIX"/> and ends with <see cref="SYMBOL_DELIMITER_SUFFIX"/>. 
        /// It may also have one or more <see cref="TOKEN_DIVISOR"/> in between.
        /// </remarks>
        private static bool ValidateVariable(string symbol)
        {
            return RegexMatchVariables.IsMatch(symbol);
        }

        /// <summary>
        /// Validates that the specified string is a valid symbol reference.
        /// </summary>
        /// <param name="symbol">The string to validate as a symbol reference.</param>
        /// <returns>
        /// True if the specified string is a valid symbol reference, 
        /// False otherwise.
        /// </returns>
        /// <remarks>
        /// A valid symbol reference begins with <see cref="SYMBOL_DELIMITER_PREFIX"/>, followed by one one <see cref="REFERENCE_IDENTIFIER_PREFIX"/> 
        /// and ends with <see cref="SYMBOL_DELIMITER_SUFFIX"/>. 
        /// </remarks>
        private static bool ValidateReference(string symbol)
        {
            return RegexMatchReferences.IsMatch(symbol);
        }

        /// <summary>
        /// Cleans a token member by removing leading and trailing quotation marks 
        /// and replacing escaped characters with intended characters.
        /// </summary>
        /// <param name="dirty">The string to be cleaned.</param>
        /// <returns>
        /// A cleaned string where any leading and trailing quotation marks have been removed 
        /// and escaped characters have been replaced.
        /// </returns>
        private static string CleanMember(string dirty)
        {
            if (dirty == null)
                return String.Empty;

            if (String.IsNullOrEmpty(dirty.Trim()))
                return String.Empty;

            // Clean the string with the Regex, 
            // e.g. remove leading and trailing quotation marks.
            string cleaned = RegexCleanMember.Match(dirty).Value;

            // Replace escaped characters.
            // Note: Do not use Regex.Unescape(string) as it may also 
            // inadvertently "clean" other intended escape sequences.
            cleaned = Regex.Replace(cleaned, Regex.Escape(QUOTATION_MARK_REGEXSAFE), QUOTATION_MARK);
            cleaned = Regex.Replace(cleaned, Regex.Escape(BACKSLASH_REGEXSAFE), BACKSLASH);

            return cleaned;
        }

        /// <summary>
        /// Gets an array containing the indices of the starting character of each 
        /// token and its corresponding length in the specified pattern.
        /// </summary>
        /// <param name="pattern">The pattern to get the token starting indices for.</param>
        /// <returns>
        /// An array with the index for the leading character for each token, and the token's length.
        /// </returns>
        public static int[,] GetIndices(string pattern)
        {
            if (String.IsNullOrEmpty(pattern))
                return null;

            if (String.IsNullOrEmpty(pattern.Trim()))
                return null;

            /*
             * NOTE:
             * This method can be optimized.
             * Currently, it locates duplicates, which is unnecessary.
             */

            List<int> beginnings = new List<int>();
            List<int> lengths = new List<int>();
            List<int> type = new List<int>();

            // Calculate the absolute start index and end index for 
            // each symbol in the specified pattern.
            MatchCollection symbols = RegexFindSymbols.Matches(pattern);
            foreach (Match symbol in symbols)
            {
                // Find all start indices of the current symbol.
                int start = 0;
                int previous = 0;
                do
                {
                    // Try to get the start position of the symbol string.
                    start = pattern.IndexOf(symbol.Value, previous, StringComparison.CurrentCultureIgnoreCase);

                    // Store the location, length and type.
                    if (start > -1)
                    {
                        beginnings.Add(start);
                        lengths.Add(symbol.Length);
                        type.Add(Convert.ToInt32(ValidateReference(symbol.Value)));
                        previous = start + symbol.Length;
                    }
                } while (start > -1);
            }

            // Copy the indices to a two-dimensional array.
            int[,] indices = new int[beginnings.Count, 3];
            for (int i = 0; i < beginnings.Count; i++)
            {
                indices[i, 0] = beginnings[i];
                indices[i, 1] = lengths[i];
                indices[i, 2] = type[i];
            }

            return indices;
        }
        #endregion Static Methods.
    }
}